#pragma once

#include "../material/Material.hpp"
#include "../mesh/Mesh.hpp"

class ModelNode{

	friend class Model;
	
private:

	Mesh* mesh;
	
public:

	void setMesh(Mesh* mesh);
	
private:

	Material* material;
	
public:

	void setMaterial(Material* material);
	
private:

	GLboolean visibleFlag = true;	
	
public:

	void show();
	
	void hide();
	
	const GLboolean isVisible() const;
	
private:

	GLboolean enableFlag = true;
	
public:

	void enable();
	
	void disable();

	const GLboolean isEnable() const;
	
private:
	
	ModelNode* owner = 0;
	
	std::set <ModelNode*> childSet;
	
public:

	void attachChild(ModelNode* child);
	
	void detachChild(ModelNode* child);
	
	void detachAllChild();
	
private:

	void draw();
	
public:

	virtual ~ModelNode();
	
};

void ModelNode::draw(){
	if (enableFlag) {
		if (visibleFlag && mesh) {
			material->bind();
			mesh->draw();
		}
		for (auto it = childSet.begin(); it != childSet.end(); ++it)
			(*it)->draw();
	}
}

void ModelNode::attachChild(ModelNode* child){
	if (child) {
		if (!child->owner) {
			child->owner = this;
			childSet.insert(child);	
		}
	}
}
	
void ModelNode::detachChild(ModelNode* child){
	if (child){
		if (child->owner == this) {
			childSet.erase(child);
			child->owner = 0;
		}
	}
}
	
void ModelNode::detachAllChild(){
	childSet.clear();
}

ModelNode::~ModelNode(){
}

const GLboolean ModelNode::isEnable() const{
	return enableFlag;
}

const GLboolean ModelNode::isVisible() const{
	return visibleFlag;
}

void ModelNode::show(){
	visibleFlag = true;
}
	
void ModelNode::hide(){
	visibleFlag = false;
}

void ModelNode::enable(){
	enableFlag = true;
}
	
void ModelNode::disable(){
	enableFlag = false;
}

void ModelNode::setMesh(Mesh* mesh){
	ModelNode::mesh = mesh;
}

void ModelNode::setMaterial(Material* material){
	ModelNode::material = material ? material : &defaultMaterial;
}

